<template>
    <!-- 先遍历点位数组，然后点击点位后，在弹窗内显示该点位信息 -->
    <div v-for="(item, index) in pointData" :key="index">
        <InfoWindow v-if="pointId == item.id" @close="pointId = ''">
            <div class="title">{{ item.properties.name }}</div>
            <div class="main">
                <div class="item">经度：{{ item.geometry.coordinates[0] }}</div>
                <div class="item">纬度：{{ item.geometry.coordinates[1] }}</div>
            </div>
        </InfoWindow>
    </div>
</template>

<script setup lang="ts">
import InfoWindow from '@/components/InfoWindow/index.vue'
import { ref, reactive } from "vue";
import { useVueCesium } from 'vue-cesium'
import type { VcViewerProvider, VcReadyObject } from 'vue-cesium/es/utils/types'
import jsonData from './test.json'

const pointData = ref(jsonData.features)
const pointId = ref('')

const $vc: VcViewerProvider = useVueCesium()

$vc.creatingPromise.then((readyObj: VcReadyObject) => {

    let Cesium: any = readyObj.Cesium
    let viewer = readyObj.viewer
    let geojson = new URL('./test.json', import.meta.url).href;

    initCluster(viewer)

    // 笛卡尔坐标转经纬度
    function cartesianToDegrees(cartesian) {
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
        var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
        // var heightString = cartographic.height;
        return {
            lng: longitudeString,
            lat: latitudeString,
            height: 1000
        };
    }

    // 点聚合功能效果
    function initCluster(viewer) {
        new Cesium.GeoJsonDataSource().load(geojson).then(dataSource => {

            viewer.dataSources.add(dataSource);

            // 设置聚合参数
            dataSource.clustering.enabled = true;
            dataSource.clustering.pixelRange = 60;
            dataSource.clustering.minimumClusterSize = 2;

            // foreach用于调用数组的每个元素，并将元素传递给回调函数。
            dataSource.entities.values.forEach(entity => {
                console.log(entity);
                let name = entity.name

                // 将点拉伸一定高度，防止被地形压盖
                entity.position._value.z += 50.0;
                // 使用大小为64*64的icon，缩小展示poi
                entity.billboard = {
                    image: new URL('./icons/poi.png', import.meta.url).href,
                    width: 32,
                    height: 32,
                };
                entity.label = {
                    text: name,
                    font: 'bold 15px Microsoft YaHei',
                    // 竖直对齐方式
                    verticalOrigin: Cesium.VerticalOrigin.CENTER,
                    // 水平对齐方式
                    horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
                    // 偏移量
                    pixelOffset: new Cesium.Cartesian2(15, 0),
                };
                entity.properties = {
                    onClick: () => {
                        pointId.value = entity.id
                        let pos = cartesianToDegrees(entity.position._value)
                        viewer.camera.flyTo({
                            //经度、纬度、高度
                            destination: Cesium.Cartesian3.fromDegrees(pos.lng, pos.lat, pos.height),
                            // destination: entity.position._value,
                            orientation: {
                                heading: Cesium.Math.toRadians(0), // 水平偏角，默认正北 0
                                pitch: Cesium.Math.toRadians(-90), // 俯视角，默认-90，垂直向下
                                roll: 0, // 旋转角
                            },
                            duration: 3 //过渡时间
                        });
                    },
                };
            });

            // 添加监听函数
            dataSource.clustering.clusterEvent.addEventListener(
                function (clusteredEntities, cluster) {
                    // 关闭自带的显示聚合数量的标签
                    cluster.label.show = false;
                    cluster.billboard.show = true;
                    cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;

                    // 根据聚合数量的多少设置不同层级的图片以及大小
                    if (clusteredEntities.length >= 15) {
                        cluster.billboard.image = combineIconAndLabel(new URL('./icons/cluster_4.png', import.meta.url).href, clusteredEntities.length, 64);
                        cluster.billboard.width = 72;
                        cluster.billboard.height = 72;
                    } else if (clusteredEntities.length >= 10) {
                        cluster.billboard.image = combineIconAndLabel(new URL('./icons/cluster_3.png', import.meta.url).href, clusteredEntities.length, 64);
                        cluster.billboard.width = 56;
                        cluster.billboard.height = 56;
                    } else if (clusteredEntities.length >= 5) {
                        cluster.billboard.image = combineIconAndLabel(new URL('./icons/cluster_2.png', import.meta.url).href, clusteredEntities.length, 64);
                        cluster.billboard.width = 48;
                        cluster.billboard.height = 48;
                    } else {
                        cluster.billboard.image = combineIconAndLabel(new URL('./icons/cluster_1.png', import.meta.url).href, clusteredEntities.length, 64);
                        cluster.billboard.width = 40;
                        cluster.billboard.height = 40;
                    }
                }
            )
        });
    }


    /**
     * @description: 将图片和文字合成新图标使用（参考Cesium源码）
     * @param {*} url：图片地址
     * @param {*} label：文字
     * @param {*} size：画布大小
     * @return {*} 返回canvas
     */
    function combineIconAndLabel(url, label, size) {
        // 创建画布对象
        let canvas = document.createElement('canvas');
        canvas.width = size;
        canvas.height = size;
        let ctx = canvas.getContext("2d");

        let promise = new Cesium.Resource.fetchImage(url).then(image => {
            // 异常判断
            try {
                // 如果文字没有居中，可以调整下面参数
                ctx.drawImage(image, 7, 5);
            } catch (e) {
                console.log(e);
            }

            // 渲染字体
            // font属性设置顺序：font-style, font-variant, font-weight, font-size, line-height, font-family
            ctx.fillStyle = Cesium.Color.WHITE.toCssColorString();
            ctx.font = 'bold 20px Microsoft YaHei';
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillText(label, size / 2, size / 2);

            return canvas;
        });
        return promise;
    }
})

</script>

<style lang="scss" scoped>
.main {
    width: 300px;
    height: 300px;
    color: #fff;
    padding: 20px 0 0;

    .item {
        padding: 5px 0;
    }
}
</style>